/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.elem;

import java.awt.*;
import java.util.*;

import org.w3c.dom.*;

import self.awt.*;
import self.awt.painter.*;
import self.gee.*;
import self.lang.*;
import self.xml.*;

public class ButtonView extends ARectangularHandledElement {
	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
  final static public int PUSH = 0;
  final static public int CHECKBOX = 1;
  final static public int RADIO = 2;

  final static public boolean LABEL_RIGHT = true;
  final static public boolean LABEL_LEFT = false;

  final static public String LABEL_PROP = "label";
  final static public String RIGHT_SIDE_PROP = "rightSide";
  final static public String TYPE_PROP = "type";
  final static public String SELECTED_PROP = "selected";

  final static public String AID_PROP = "aid";

  final static private Font buttonFont = new Font( "Arial", Font.PLAIN, 12 );

  private String  label = "Button";
  private boolean isLabelOnRightSide = LABEL_RIGHT;
  private boolean isSelected = false;
  private int type = PUSH;
  private String aidLink;

  transient protected ButtonPaintContext   buttonContext = new ButtonPaintContext();

  protected           TextPainter         textPainter;

  public ButtonView() {
    fig.setBounds( 10, 10, 78, 28 );
    resetFrame();
//    PainterManager.registerOwner( this );
//    textPainter = (TextPainter) PainterManager.getPainterForOwner( this, TextPainter.class );
  }

  public void       setLayer( IDiagramLayer layerToDrawOn, boolean add ) {
    super.setLayer( layerToDrawOn, add );
    textPainter = (TextPainter) PainterManager.getPainterForOwner( layer, TextPainter.class );
  }

  // IEditableElement support
  public void       getProperties( Map store ) {
    store.put( LABEL_PROP, label );
    store.put( RIGHT_SIDE_PROP, isLabelOnRightSide ? Boolean.TRUE: Boolean.FALSE );
    store.put( SELECTED_PROP, isSelected ? Boolean.TRUE: Boolean.FALSE );
    store.put( TYPE_PROP, new Integer(type) );
    store.put( AID_PROP, aidLink );
  }

  public void       setProperties( Map data ) {
    Boolean rightSide = (Boolean) data.get( RIGHT_SIDE_PROP );
    isLabelOnRightSide = rightSide.booleanValue();
    Boolean sel = (Boolean) data.get( SELECTED_PROP );
    isSelected = sel.booleanValue();
    label = (String) data.get( LABEL_PROP );
    Integer typ = (Integer) data.get( TYPE_PROP );
    type = typ.intValue();
    aidLink = (String) data.get( AID_PROP );
    resetFrame();
    layer.setDirty();
  }

  // IPersistentElement support
  public void readFrom( Node self, HashMap idObjLookUp ) throws DOMException {
    super.readFrom( self, idObjLookUp );
    label = DomUtils.getElementAttribute( self, LABEL_PROP );
    try {
      String rightSideAsString = DomUtils.getElementAttribute( self, RIGHT_SIDE_PROP );
      isLabelOnRightSide = BooleanUtils.toValue( rightSideAsString );
    } catch ( Exception err ) {
    	// nothing to do.
    }
    try {
      String selAsString = DomUtils.getElementAttribute( self, SELECTED_PROP );
      isSelected = BooleanUtils.toValue( selAsString );
    } catch ( Exception err ) {
    	// nothing to do.
    }
    try {
      String typeAsString = DomUtils.getElementAttribute( self, TYPE_PROP );
      type = Integer.parseInt( typeAsString );
    } catch ( Exception err ) {
    	// nothing to do.
    }
    aidLink = DomUtils.getElementAttribute( self, AID_PROP, null );
    resetFrame();
  }

  public void writeTo( Document doc, Element self, HashMap objIdLookup ) throws DOMException {
    super.writeTo( doc, self, objIdLookup );
    DomUtils.setElementAttribute( self, LABEL_PROP, label );
    if ( type != PUSH )
      DomUtils.setElementAttribute( self, TYPE_PROP, "" + type );
    if ( isSelected )
      DomUtils.setElementAttribute( self, SELECTED_PROP, "" + isSelected );
    if ( !isLabelOnRightSide )
      DomUtils.setElementAttribute( self, RIGHT_SIDE_PROP, "" + isLabelOnRightSide );
    if ( !StringUtils.isNullOrEmpty(aidLink) )
      DomUtils.setElementAttribute( self, AID_PROP, StringUtils.toEmptyIfNull(aidLink) );
  }

  public void       paint( Graphics surface ) {
//    System.out.println("moooo2");
    if ( outlineOnly ) {
      surface.setColor(frameColor);
      surface.drawRect( fig.x, fig.y, fig.width, fig.height );
      return;
    }

    GraphicAttrs attrs = null;
    boolean paintSymbol = aidLink != null;
    if ( paintSymbol ) {
      attrs = new GraphicAttrs( surface );
      surface.setColor(Color.lightGray);
      surface.setFont(new Font("Arial", Font.PLAIN, 9));
      surface.drawString("", -10, -10 );
      surface.setColor( frameColor );
      SymbolPaintManagerUtils.startSymbol( surface, this, aidLink );
    }
    try {
      switch ( type ) {
        case CHECKBOX: paintCheckBoxButton( surface ); break;
        case RADIO:    paintRadioButton( surface ); break;
        default:       paintPushButton( surface ); break;
      }
      paintButtonLabel( surface );
    } finally {
      if ( paintSymbol ) {
        SymbolPaintManagerUtils.endSymbol( surface );
        attrs.reset( surface );
      }
    }
  }

  private void paintPushButton( Graphics surface ) {
    surface.setColor( Color.lightGray );
    surface.fillRect( fig.x, fig.y, fig.width, fig.height );
    surface.setColor(frameColor);
    surface.drawRect( fig.x, fig.y, fig.width, fig.height );
  }

  private void paintButtonLabel( Graphics surface ) {
    textPainter.paint( surface, buttonContext, false );
  }

  private void paintCheckBoxButton( Graphics surface ) {
    surface.setColor( frameColor );
    int xPos =  fig.x + ( isLabelOnRightSide ? 2: fig.width - 16  );
    int yPos = fig.y + 4;
    surface.drawRect( xPos, yPos, 12, 12 );
    if ( isSelected ) {
      surface.drawLine( xPos + 2, yPos + 2, xPos + 9, yPos + 9 );
      surface.drawLine( xPos + 2, yPos + 9, xPos + 9, yPos + 2 );
    }
  }

  private void paintRadioButton( Graphics surface ) {
    surface.setColor( frameColor );
    int xPos =  fig.x + ( isLabelOnRightSide ? 2: fig.width - 16 );
    int yPos = fig.y + 4;
    surface.drawOval( xPos, yPos, 12, 12 );
    if ( isSelected )
      surface.fillOval( xPos + 2, yPos + 2, 8, 8 );
  }

  protected void resetFrame() {
    buttonContext.resetBounds( fig );
  }

  protected class ButtonPaintContext extends ATextRenderInfoAdapter {
    private Rectangle bounds = new Rectangle();

    public ButtonPaintContext() {
      format = ITextRenderInfo.CENTERED_FORMAT;
    }

    public void resetBounds( Rectangle r ) {
      if ( type == PUSH )
        resetForPushButton( r );
      else
        resetForNonPushButton( r );
    }

    private void resetForPushButton( Rectangle r ) {
      format = ITextRenderInfo.CENTERED_FORMAT;
      bounds.y = r.y + (r.height - 18) / 2;
      bounds.height = 18;
      bounds.x = r.x + 2;
      bounds.width = r.width - 2;
    }

    private void resetForNonPushButton( Rectangle r ) {
      format = ITextRenderInfo.WRAPPED_FORMAT;
      bounds.y = r.y + 2;
      bounds.height = r.height - 2;
      bounds.x = r.x + (isLabelOnRightSide ? 20: 2 );
      bounds.width = r.width - 20;
    }

    public String     getText() {
      return label;
    }

    public Rectangle  getBounds() {
      return bounds;
    }

    public Font       getFont() {
      return buttonFont;
    }

    public Color      getColor() {
      return Color.black;
    }
  }
}